<?php

/**
 * 瞎猜-竞猜
 * @since 1.0 2017-10-16
 */
class guessingModel extends NewModel {

    /**
     * redis对象实例
     * @var [type]
     */
    protected static $xiacai_redis, $guessinglog_redis, $video_redis, $user_redis;
    protected static $guessing_log_model, $user_model, $coin_log_model, $user_guessing_log_model;

    public function __construct() {
        parent::__construct('');

        if (!self::$user_redis) {
            fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/BaseRedisService.php');
            fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/XiacaiRedisService.php');
            fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/GuessingLogRedisService.php');
            fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
            fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/UserRedisService.php');
            self::$user_redis = new UserRedisService();
            self::$xiacai_redis = new XiacaiRedisService();
            self::$guessinglog_redis = new GuessingLogRedisService();
            self::$video_redis = new VideoRedisService();
            // module
            self::$guessing_log_model = self::build('guessing_log');
            self::$user_model = self::build('user');
            self::$coin_log_model = self::build('coin_log');
            self::$user_guessing_log_model = self::build('user_guessing_log');
        }
    }

    public function crontab() {
        $microtime = microtime(1);
        if (self::$guessinglog_redis->isLock()) {
            return array('is_lock');
        }
        self::$guessinglog_redis->lock(); // 锁定独占操作
        $guessingloglist = self::$guessing_log_model->field('id, xiacai_id')->select(array('is_notify=0 and status=2')); // 已开奖未通知的竞猜日志列表
        if ($guessingloglist) {
            foreach ($guessingloglist as $guessinglog) { // 循环每轮竞猜
                $this->drawOneGuessing($guessinglog);
            }
        }
        //$this->clearGameLog(); // 将关闭的直播游戏记录移入历史记录(把game_log表的数据转移到game_log_history表,user_game_log表的数据转移到user_game_log_history表，并从game_log表和user_game_log表删除转移过的记录)
        $return_data['time'] = microtime(1) - $microtime;
        self::$guessinglog_redis->unLock(); // 解锁
        return $return_data;
    }

    public function drawOneGuessing($guessinglog, $win_guessing_id) {
        $return_data = array();
        $guessing_log_id = intval($guessinglog['id']);
        $xiacai_id = intval($guessinglog['xiacai_id']);
        $group_id = strval($guessinglog['group_id']); // group_id必需是字符串，否则腾讯云会返回失败
        $video_id = intval($guessinglog['room_id']);
        $user_bet = json_decode($guessinglog['user_bet'], true);
        $cheat = true; // 作弊开关
        $video_live_in = self::$video_redis->getOne_db($video_id, 'live_in'); // 直播状态
        $guessing_log_status = intval($guessinglog['status']); // 竞猜状态
        // 从redis获取竞猜倍率
        $guessing_list = self::$xiacai_redis->getGuessing($xiacai_id);
        debugmsg('guessingModel::drawOneGuessing()', compact('win_guessing_id', 'guessing_log_id', 'video_id', 'group_id', 'video_live_in', 'guessing_log_status'));
        if ($video_live_in && $guessing_log_status == 2) { // 如果正在直播且游戏正在进行
            // 计算投注结果
            $win_ratio = 0; // 获胜赔率
            foreach ($guessing_list as $guessing_id => $guessing_row_json) {
                $guessing_row = json_decode($guessing_row_json, true);
                if ($guessing_id == $win_guessing_id) {
                    $win_ratio = $guessing_row['win_ratio']; // 获胜赔率
                }
            }
            // 更新开奖竞猜id到数据库和redis
            $data['user_bet'] = $guessinglog['user_bet']; // 真实用户投注
            $data['all_bet'] = $guessinglog['all_bet']; // 所有用户投注
            $data['is_notify'] = 1; // 已做开奖处理和推送通知
            self::$guessing_log_model->update($data, array('id' => $guessing_log_id));
            self::$guessinglog_redis->update_db($guessing_log_id, $data, false);

            // 下注结算
            self::$user_guessing_log_model->update(array('status' => 1), array('guessing_log_id' => $guessing_log_id, 'guessing_id' => $guessing_id)); // 本轮下注用户开奖状态改为中奖
            self::$user_guessing_log_model->update(array('status' => 2), array('guessing_log_id' => $guessing_log_id, 'status' => 0)); // 本轮剩余下注用户开奖状态改为未中奖
            // MySQL结束游戏
            $user_bet = json_decode($guessinglog['user_bet'], true); // 真实用户下注数据
            $win_amount = $win_ratio * $user_bet[$win_guessing_id];
            $income = array_sum($user_bet) - $win_amount; // 计算净收益 总下注金额 减去 获奖总额
            $final_income = $income; // 最终收入
            $commission = 0;
            debugmsg('guessingModel::drawOneGuessing()', compact('user_bet', 'win_ratio', 'win_amount', 'income', 'guessing_log_id', 'video_id'), false);
            Connect::beginTransaction();
            // 玩家收入
            if ($win_amount) { // 如果开奖后赢家那桌有真人投注的获胜奖金
                if (self::$user_model->multiAddCoinForGuessing($guessing_log_id, $win_guessing_id, $win_ratio) === false) { // 更新用户表金币+=获奖收益
                    Connect::rollback();
                    $return_data[$guessing_log_id] = 'error:' . __LINE__ . ' sql:' . self::$user_model->getLastSql();
                    return;
                }
                // 批量插入金币记录
                if (self::$coin_log_model->multiAddLogForGuessing($guessing_log_id, $win_guessing_id, $win_ratio) === false) { // 更新用户金币表
                    Connect::rollback();
                    $return_data[$guessing_log_id] = 'error:' . __LINE__ . ' sql:' . self::$coin_log_model->getLastSql();
                    return;
                }
                // 平台抽成
                $m_config = load_auto_cache("m_config");
                $game_commission = +$m_config['game_commission'];
                if ($game_commission) {
                    if (self::$user_model->multiAddCoinForGuessing($guessing_log_id, $win_guessing_id, -$game_commission / 100 * $win_ratio) === false) {
                        Connect::rollback();
                        $return_data[$guessing_log_id] = 'error:' . __LINE__ . ' sql:' . self::$user_model->getLastSql();
                        return;
                    }
                    // 批量插入金币记录
                    if (self::$coin_log_model->multiAddLogForGuessing($guessing_log_id, $win_guessing_id, -$game_commission / 100 * $win_ratio, '玩家收入平台抽成') === false) {
                        Connect::rollback();
                        $return_data[$guessing_log_id] = 'error:' . __LINE__ . ' sql:' . $coin_log_model->getLastSql();
                        return;
                    }
                }
                $win_rate = (1 - ($game_commission) / 100);
                $win_times = $win_ratio * $win_rate;
                // 批量插入获胜记录
                if (self::$user_guessing_log_model->multiAddLog($guessing_log_id, $win_guessing_id, $win_times) === false) {
                    Connect::rollback();
                    $return_data[$guessing_log_id] = 'error:' . __LINE__ . ' sql:' . self::$user_guessing_log_model->getLastSql();
                    return;
                }
            }

            Connect::commit();
            // 处理普通玩家金币等数据
            $ids = array();
            if ($win_amount > 0) {
                $res = self::$user_guessing_log_model->field('user_id')->group('user_id')->select(array('guessing_log_id' => $guessing_log_id));
                foreach ($res as $value) {
                    $ids[] = $value['user_id'];
                }
            }
            if (!empty($ids)) {
                user_deal_to_reids($ids); // 将用户表的diamonds,use_diamonds,score,ticket,user_level,refund_ticket 几个字段值,同步到redis,红黑开奖金币未更新原因在这里
            }
            // 推送--竞猜开奖
            $ext = array(
                'type' => 52,
                'room_id' => $video_id,
                'desc' => '----',
                'time' => NOW_TIME,
                'xiacai_id' => $xiacai_id,
                'guessing_log_id' => $guessing_log_id,
                'guessing_status' => 2, // 0:未开始,1:进行中,2:已开奖
                'guessing_action' => 4, // // 1:开始; 2:下注; 3:停止; 4:结算;
                'guessing_data' => array(
                    'win_guessing_id' => $win_guessing_id,
                    'user_bet' => array(),
                    'all_bet' => array(),
                ),
                'account_diamonds' => 0,
                'coin' => 0,
                'guessing_my_bet' => array('status' => 0, 'bet_amount' => 0, 'guessing_id' => 0), // 我自己的下注数据
            );
            $res = timSystemNotify($group_id, $ext);
            debugmsg('guessingModel::drawOneGuessing()-推送消息', compact('ext', 'res', 'guessing_log_id', 'video_id', 'group_id'));
        } else { // 如果直播关闭或游戏关闭则返还投注
            // 返还投注
            Connect::beginTransaction();
            if (self::$guessing_log_model->update(array('status' => 2), array('id' => $guessing_log_id)) === false) {
                Connect::rollback();
                $return_data[$guessing_log_id] = 'error:' . __LINE__;
                return $return_data;
            }
            self::$guessinglog_redis->update_db($guessing_log_id, array('status' => 2), false);
            if (self::$user_model->returnCoinForGuessing($guessing_log_id) === false) {
                Connect::rollback();
                $return_data[$guessing_log_id] = 'error:' . __LINE__;
                return $return_data;
            }
            if (self::$coin_log_model->returnCoin($guessing_log_id) === false) {
                Connect::rollback();
                $return_data[$guessing_log_id] = 'error:' . __LINE__;
                return $return_data;
            }
            if ($GLOBALS['db']->affected_rows()) {
                $res = self::$user_guessing_log_model->field('user_id')->group('user_id')->select(array('id' => $guessing_log_id));
                $ids = array();
                foreach ($res as $value) {
                    $ids[] = $value['user_id'];
                }
                user_deal_to_reids($ids);
            }
            Connect::commit();
            $ext = array(
                'type' => 51,
                'desc' => '',
            );
            $res = timSystemNotify($group_id, $ext);
            $return_data[$guessing_log_id] = array(
                'type' => 'end_return',
                'id' => $guessing_log_id,
                'res' => $res,
            );
        }
        // 清空竞猜游戏关联
        $update_xiacai['guessing_log_id'] = 0;
        Model::build('xiacai')->update($update_xiacai, array('id' => $xiacai_id));
        self::$xiacai_redis->update_db($data['id'], $update_xiacai);
        return $return_data;
    }

    public function stopGuessing($guessinglog) { // 如果直播关闭或游戏关闭则返还投注
        // 更新开奖竞猜id到数据库和redis
        $data['status'] = 4;
        $data['user_bet'] = $guessinglog['user_bet']; // 真实用户投注
        $data['all_bet'] = $guessinglog['all_bet']; // 所有用户投注
        $guessing_log_id = $guessinglog['id'];
        $group_id = strval($guessinglog['group_id']);
        $data['is_notify'] = 1; // 已做开奖处理和推送通知
        self::$guessing_log_model->update($data, array('id' => $guessing_log_id));
        self::$guessinglog_redis->update_db($guessing_log_id, $data, false);
        // 返还投注
        Connect::beginTransaction();
        if (self::$guessing_log_model->update(array('status' => 2), array('id' => $guessing_log_id)) === false) {
            Connect::rollback();
            $return_data[$guessing_log_id] = 'error:' . __LINE__;
            return $return_data;
        }
        self::$guessinglog_redis->update_db($guessing_log_id, array('status' => 2), false);
        if (self::$user_model->returnCoinForGuessing($guessing_log_id) === false) {
            Connect::rollback();
            $return_data[$guessing_log_id] = 'error:' . __LINE__;
            return $return_data;
        }
        if (self::$coin_log_model->returnCoin($guessing_log_id) === false) {
            Connect::rollback();
            $return_data[$guessing_log_id] = 'error:' . __LINE__;
            return $return_data;
        }
        if ($GLOBALS['db']->affected_rows()) {
            $res = self::$user_guessing_log_model->field('user_id')->group('user_id')->select(array('id' => $guessing_log_id));
            $ids = array();
            foreach ($res as $value) {
                $ids[] = $value['user_id'];
            }
            user_deal_to_reids($ids);
        }
        Connect::commit();
        $ext = array(
            'type' => 51,
            'desc' => '',
        );
        $res = timSystemNotify($group_id, $ext);
        $return_data[$guessing_log_id] = array(
            'type' => 'end_return',
            'id' => $guessing_log_id,
            'res' => $res,
        );
        return $return_data;
    }

    function sortBet($sum_v, $user_bet) {
        asort($sum_v);
        $akeys = array_keys($user_bet);
        $asortkeys = array();
        $aout = [];
        foreach ($sum_v as $key => $val) {
            $asortkeys[] = $akeys[$key];
        }
        foreach ($asortkeys as $key) {
            $aout[$key] = $user_bet[strval($key)];
        }
        return $aout;
    }

    /**
     * 将关闭的直播游戏记录移入历史记录(把game_log表的数据转移到game_log_history表,user_game_log表的数据转移到user_game_log_history表，并从game_log表和user_game_log表删除转移过的记录)
     * @return void
     */
    public function clearGuessingLog() {
        $return = [];
        $table = DB_PREFIX . 'game_log';
        $video_table = DB_PREFIX . 'video';

        $res = $GLOBALS['db']->getOne("SELECT COUNT(1) FROM `$table` WHERE podcast_id NOT IN(SELECT user_id FROM `$video_table` WHERE live_in = 1) AND `status`=2");
        $return[__LINE__] = $res;
        if ($res) {
            $history = DB_PREFIX . 'game_log_history';
            $log_table = DB_PREFIX . 'user_game_log';
            $log_history = DB_PREFIX . 'user_game_log_history';
            Connect::beginTransaction();
            /**
             * 游戏记录迁移
             * @var [type]
             */
            $res = Connect::exec("INSERT INTO `$history`(SELECT * FROM `$table` WHERE podcast_id NOT IN(SELECT user_id FROM `$video_table` WHERE live_in = 1) AND `status`=2)");
            if ($res === false) {
                Connect::rollback();
                $return[__LINE__] = $res;
                return $return;
            }
            $res = Connect::exec("DELETE FROM `$table` WHERE podcast_id NOT IN (SELECT user_id FROM `$video_table` WHERE live_in = 1) AND `status`=2");
            if ($res === false) {
                Connect::rollback();
                $return[__LINE__] = $res;
                return $return;
            }
            /**
             * 下注记录迁移
             * @var [type]
             */
            $res = Connect::exec("INSERT INTO `$log_history`(SELECT * FROM `$log_table` WHERE `game_log_id` NOT IN(SELECT `id` FROM `$table`))");
            if ($res === false) {
                Connect::rollback();
                $return[__LINE__] = $res;
                return $return;
            }
            $res = Connect::exec("DELETE FROM `$log_table` WHERE `game_log_id` NOT IN (SELECT `id` FROM `$table`)");
            if ($res === false) {
                Connect::rollback();
                $return[__LINE__] = $res;
                return $return;
            }
            Connect::commit();
        }
        return $return;
    }

}
